package com.cskaoyan.javase.oop3._2inner._5lambda._2usecase;

/**
 * Lambda表达式本质上是一个功能接口的子类对象
 * 更进一步,实际上我们需要的是Lambda表达式重写的一个方法
 *
 * 在实际的开发中,Lambda表达式的重写方法,往往在其他方法中表示一种规则
 * 比如排序(sort)
 * 比如过滤(filter)
 * 再比如映射(map)
 * 总之Lambda表达式重写的接口方法,可以在方法中表示一个规则
 * 这样的话,规则就可以在具体使用时,具体定义
 * 代码的灵活性和扩展性就会很好.
 *
 *
 * @since 10:41
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        String[] arr = {"666", "666", "hello", "666张三", "777"};

        // 测试
        // 规则1:什么都不过滤,全要
        String[] newArr = getNewStringArrByFilter(arr, str -> true);
        for (String s : newArr) {
            System.out.println(s);
        }
        System.out.println("----------------------------");
        // 规则2: 如果是"666",我都不要,删除"666"元素
        /*String[] newArr2 = getNewStringArrByFilter(arr, str -> {
            if (str.equals("666")) {
                return false;
            }
            return true;
        });*/
        // 以上简化
        String[] newArr2 = getNewStringArrByFilter(arr, str -> !str.equals("666"));
        for (String s : newArr2) {
            System.out.println(s);
        }
        System.out.println("----------------------");
        // 规则3: 我只要以"666"开头的元素
        // String字符串如何判断以XXX开头
        // String类本身的成员方法startsWith(String)
        /*String[] newArr3 = getNewStringArrByFilter(arr, str -> {
            if (str.startsWith("666")) {
                return true;
            }
            return false;
        });*/
        String[] newArr3 = getNewStringArrByFilter(arr, str -> str.startsWith("666"));
        for (String s : newArr3) {
            System.out.println(s);
        }

    }
    // 需求: 根据实际需求来过滤String数组
    /*
        过滤是在原先数组的基础上,过滤掉不需要的元素,然后生成新的数组
        既然是过滤,就需要过滤规则,我们可以用Lambda表达式的实现对象中的方法来表示过滤规则
     */

    /**
     * 让oldArr数组中的每个元素接受规则检查,返回true表示需要的元素,留下
     * 返回false表示不需要的元素,丢弃
     * @since 10:51
     * @param oldArr 被过滤的旧数组
     * @param filter 表示过滤的规则
     * @return java.lang.String[]
     * @author wuguidong@cskaoyan.onaliyun.com
     */
    public static String[] getNewStringArrByFilter(String[] oldArr, StringArrFiler filter) {
        // 1.首先需要计数,获取留下元素的个数,这是新数组的长度
        int count = 0;
        for (String element : oldArr) {
            // 将每个元素传入filter的accept方法,通过比较规则,校验
            // 方法返回true的留下来,false被过滤掉
            if (filter.accept(element)) {
                count++;
            }
        }
        // 2.创建新数组,新数组的长度就是能够留下来元素的个数
        String[] newArr = new String[count];
        // 3.拷贝元素,将符合过滤规则,需要留下的元素,赋值进新数组
        int newIndex = 0;
        for (String element : oldArr) {
            // 再次过滤,完成赋值
            if (filter.accept(element)) {
                // 需要留下来的元素,赋值给新数组
                newArr[newIndex] = element;
                newIndex++;
            }
        }
        return newArr;
    }
}

// 功能接口,表示过滤,表示对String数组中元素的过滤规则
@FunctionalInterface
interface StringArrFiler {
    /**
     * 方法返回true时,表示这个元素需要
     * 方法返回false时,表示这个元素不需要,被过滤掉
     * @since 10:49
     * @param str 被过滤数组中的String元素
     * @return boolean
     * @author wuguidong@cskaoyan.onaliyun.com
     */
    boolean accept(String str);
}
